﻿using Bootloader.zlgcan;
using System;
using System.Collections.Generic;
using System.Data.SqlTypes;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using ZLGAPI;
using static Bootloader.Services.FileParser;
using System.Security.Cryptography;
using System.Drawing;

namespace Bootloader.Servicers
{
    // 编程异常类，用于抛出异常用
    public class ProgrammingException : Exception
    {

        // 存储 UDS 错误码（可选）
        public byte? ErrorCode { get; }

        // 抛出不带参
        public ProgrammingException() { }

        // 抛出带消息
        public ProgrammingException(string message)
            : base(message) { }

        // 抛出带消息和NRC
        public ProgrammingException(string message, byte errorCode)
            : base(message)
        {
            ErrorCode = errorCode;
        }

        // 主构造函数：接受可空 errorCode
        public ProgrammingException(string message, byte? errorCode = null)
            : base(message)
        {
            ErrorCode = errorCode;
        }
    }



    public class FirmwareFlasher
    {
        // 校验模式枚举
        public enum ChecksumMode
        {
            SELF_OR_SIG_CHECK = 0,// 自校验或通过验签
            CRC32 = 1,
            SHA256 = 2,
        }

        private readonly UDS_TP _udsTpHandle = null;// UDS网络协议栈句柄

        // == 刷写文件 ==
        private readonly FlashFile _appFile = null;// APP文件
        private readonly FlashFile _flashDriverFile = null;// Flashdriver文件
        private readonly SigFile _sigFile = null;// 验签文件
        private readonly string securityDllFilePath = ".\\Security.dll";

        // == 校验方式 ==
        private FirmwareFlasher.ChecksumMode _checksumMode = ChecksumMode.SELF_OR_SIG_CHECK;

        // == 网络管理配置 ==
        private static readonly uint _NM_CanId = 0x5FF;// 网络管理报文ID
        private static readonly byte[] _NMCanFrame = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };// 唤醒报文

        // == 会话维持配置 ==
        private static readonly ushort _sessionPerCycle = 2000;// 会话维持周期

        // == 14清除DTC掩码 ==
        private static readonly byte[] _14dtcAllGroupMask = new byte[] { 0xFF, 0xFF, 0xFF };// DTC所有组掩码

        // == 31例程控制配置 ==
        private static readonly byte[] _31PreCheck = new byte[] { 0x01, 0x02, 0x03 };// 预编程条件检查（Pre-Programming Conditions Check）
        private static readonly byte[] _31EraseMemory = new byte[] { 0x01, 0xFF, 0x00 }; // 擦除（Erase Memory）
        private static readonly byte[] _31Checksum = new byte[] { 0x01, 0x02, 0x02 }; // 校验数据（Verify Data / Checksum）
        private static readonly byte[] _31CompatCheck = new byte[] { 0x01, 0xFF, 0x01 }; // 检查兼容性（Compatibility Check）

        // == 27安全解锁配置 ==
        private static readonly byte _27FblSubID = 0x11;// FBL 27解锁子服务
        private static readonly byte _27FblLevel = 0x02;// FBL 27解锁等级

        // == 2E写指纹信息 ==
        private static readonly byte[] _2EFingerprintDID = new byte[] { 0xF1, 0x84 };// 写入指纹DID
        private static readonly byte[] _2EFingerprint = new byte[] { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09 };// 指纹数据，当然也可以获取系统时间写入

        // == 11复位后延时等待时间 ==
        private static readonly int _resetDelayTime = 200;// 跳转Boot延时等待时间
        private static readonly int _fristRunDelayTime = 2000;// 刷写第一次复位延时等待时间

        public FirmwareFlasher(UDS_TP udsHandle, FlashFile appFile, FlashFile flashDriverFile, SigFile sigFile)
        {
            _udsTpHandle = udsHandle;
            _appFile = appFile;
            _flashDriverFile = flashDriverFile;
            _sigFile = sigFile;
        }

        // 设置校验方式
        public void SetCheckSumMode(FirmwareFlasher.ChecksumMode checksumMode)
        {
            _checksumMode = checksumMode;
        }

        public async Task FlashStartAsync()
        {
            await PreProgrammingAsync();
            await PerformProgrammingAsync();
            await PostProgrammingAsync();

            // 调试用
            //// 将 byte[] 转为 "01 A2 FF" 格式的十六进制字符串
            //string dataHex = BitConverter.ToString(data).Replace("-", " ");
            //Debug.WriteLine($"isPositive: {isPositive}, Data: [{dataHex}]");
        }

        // 停止刷写
        public void FlashStop()
        {
            _udsTpHandle.SetTesterPresent(false);
        }


        // 预编程
        private async Task PreProgrammingAsync()
        {
            // 唤醒报文
            for (int i = 0; i < 20; i++)
            {
                bool ok = _udsTpHandle.SendFrame(_NM_CanId, _NMCanFrame);
                if (!ok)
                {
                    throw new ProgrammingException("CAN发送失败，请检查线路连接");
                }
                await Task.Delay(10);
            }

            // 进入扩展会话（物理寻址）
            await UDS10_SessionControlAsync(UDS_TP.REQ_ADDR.PHY_ADDR, 0x03);

            // 检查刷写条件（物理寻址）
            await UDS31_RoutineCtrlAsync(_31PreCheck, "检查刷写条件");

            // 进入扩展会话（功能寻址）
            await UDS10_SessionControlAsync(UDS_TP.REQ_ADDR.FUN_ADDR, 0x83, true);

            // 关闭DTC（功能寻址）
            await UDS85_DtcControlAsync(UDS_TP.REQ_ADDR.FUN_ADDR, 0x82, true);

            // 关闭通信（功能寻址）
            await UDS28_MsgControlAsync(UDS_TP.REQ_ADDR.FUN_ADDR, 0x83, 0x03, true);
        }
        // 编程中
        private async Task PerformProgrammingAsync()
        {
            // 均为（物理寻址）
            // 进入编程会话
            await UDS10_SessionControlAsync(UDS_TP.REQ_ADDR.PHY_ADDR, 0x02);

            // 延时等待ECU调转编程会话
            await Task.Delay(_resetDelayTime);

            // 解锁电控单元
            await UDS27_SecurityAsync(_27FblSubID, _27FblLevel);

            // 写入指纹信息
            await UDS2E_DataWriteAsync(_2EFingerprintDID, _2EFingerprint, "指纹写入");

            // ==（Flashdriver）==
            // 请求数据下载
            uint blockSize = await UDS34_RequestAsync(_flashDriverFile.StartAddr, (uint)_flashDriverFile.Data.Length, "Flashdriver");

            // 数据传输
            await UDS36_TransferAsync(_flashDriverFile, blockSize, "Flashdriver");

            // 退出传输
            await UDS37_EndTransAsync("Flashdriver");

            // 完整性校验
            if (_checksumMode == ChecksumMode.SELF_OR_SIG_CHECK && _sigFile != null)
            {
                // 有验签文件
                await UDS31_RoutineCtrlAsync(_31Checksum, _sigFile.Data[0], "FlashDriver完整性校验");
            }
            else if (_checksumMode == ChecksumMode.CRC32)// CRC32
            {
                byte[] checkSum = CheckSum.CRC32(_flashDriverFile.Data);
                await UDS31_RoutineCtrlAsync(_31Checksum, checkSum, "FlashDriver完整性校验");
            }
            else if (_checksumMode == ChecksumMode.SHA256)// SHA256
            {
                byte[] checkSum = CheckSum.Sha256(_flashDriverFile.Data);
                await UDS31_RoutineCtrlAsync(_31Checksum, checkSum, "FlashDriver完整性校验");
            }
            else// 自校验
            {
                await UDS31_RoutineCtrlAsync(_31Checksum, "FlashDriver完整性校验");
            }


            // ==（App）==
            // 设置会话维持
            _udsTpHandle.SetTesterPresent(true, _sessionPerCycle);

            // 擦除内存区域
            byte[] EraseMemoryParm = new byte[4 + 4];

            EraseMemoryParm[0] = (byte)((_appFile.StartAddr >> 24) & 0xFF);
            EraseMemoryParm[1] = (byte)((_appFile.StartAddr >> 16) & 0xFF);
            EraseMemoryParm[2] = (byte)((_appFile.StartAddr >> 8) & 0xFF);
            EraseMemoryParm[3] = (byte)((_appFile.StartAddr) & 0xFF);

            EraseMemoryParm[4] = (byte)((_appFile.Data.Length >> 24) & 0xFF);
            EraseMemoryParm[5] = (byte)((_appFile.Data.Length >> 16) & 0xFF);
            EraseMemoryParm[6] = (byte)((_appFile.Data.Length >> 8) & 0xFF);
            EraseMemoryParm[7] = (byte)((_appFile.Data.Length) & 0xFF);
            await UDS31_RoutineCtrlAsync(_31EraseMemory, EraseMemoryParm, "APP擦除");

            // 关闭会话维持
            _udsTpHandle.SetTesterPresent(false);

            // 请求数据下载
            blockSize = await UDS34_RequestAsync(_appFile.StartAddr, (uint)_appFile.Data.Length, "APP");

            // 数据传输
            await UDS36_TransferAsync(_appFile, Math.Min(blockSize, 4095), "APP");

            // 退出传输
            await UDS37_EndTransAsync("APP");

            // 设置会话维持
            _udsTpHandle.SetTesterPresent(true, _sessionPerCycle);

            // 完整性校验
            if (_checksumMode == ChecksumMode.SELF_OR_SIG_CHECK && _sigFile != null)
            {
                // 有验签文件
                await UDS31_RoutineCtrlAsync(_31Checksum, _sigFile.Data[1], "APP完整性校验");
            }
            else if (_checksumMode == ChecksumMode.CRC32)// CRC32
            {
                byte[] checkSum = CheckSum.CRC32(_appFile.Data);
                await UDS31_RoutineCtrlAsync(_31Checksum, checkSum, "APP完整性校验");
            }
            else if (_checksumMode == ChecksumMode.SHA256)// SHA256
            {
                byte[] checkSum = CheckSum.Sha256(_appFile.Data);
                await UDS31_RoutineCtrlAsync(_31Checksum, checkSum, "APP");
            }
            else// 自校验
            {
                await UDS31_RoutineCtrlAsync(_31Checksum, "APP");
            }

            // 关闭会话维持
            _udsTpHandle.SetTesterPresent(false);

            // 检查兼容性
            await UDS31_RoutineCtrlAsync(_31CompatCheck, "APP兼容性检查");

            // ECU硬复位
            await UDS11_ResetAsync(UDS_TP.REQ_ADDR.PHY_ADDR, 0x01);

            // 延时等待第一次启动，有的项目第一次启动比较久，不延时久一点功能起不来会失败
            await Task.Delay(_fristRunDelayTime);
        }

        // 后编程
        private async Task PostProgrammingAsync()
        {
            // 进入默认会话（功能寻址）
            await UDS10_SessionControlAsync(UDS_TP.REQ_ADDR.FUN_ADDR, 0x81, true);

            // 清除故障码（功能寻址）
            await UDS14_ClearDtcAsync(UDS_TP.REQ_ADDR.FUN_ADDR, _14dtcAllGroupMask, true);
            await Task.Delay(20);
        }


        // 封装10会话控制方法
        private async Task UDS10_SessionControlAsync(UDS_TP.REQ_ADDR srcAddr, byte session, bool isSuppressPosRsp = false)
        {
            var (isPositive, data) = await _udsTpHandle.UdsRequestAsync(
                reqAddr: srcAddr,
                isSuppressPosRsp: isSuppressPosRsp,
                serviceId: 0x10,
                subFunction: new byte[] { session },
                parameter: null);
            if (!isPositive)
            {
                byte? nrc = data?.Length > 0 ? data[0] : (byte?)null;
                throw new ProgrammingException("10会话跳转失败", nrc);
            }
        }

        // 封装11复位方法
        private async Task UDS11_ResetAsync(UDS_TP.REQ_ADDR srcAddr, byte subFun, bool isSuppressPosRsp = false)
        {
            var (isPositive, data) = await _udsTpHandle.UdsRequestAsync(
                reqAddr: srcAddr,
                isSuppressPosRsp: isSuppressPosRsp,
                serviceId: 0x11,
                subFunction: new byte[] { subFun },
                parameter: null);
            if (!isPositive)
            {
                byte? nrc = data?.Length > 0 ? data[0] : (byte?)null;
                throw new ProgrammingException("11复位失败", nrc);
            }
        }

        // 封装14清除DTC方法
        private async Task UDS14_ClearDtcAsync(UDS_TP.REQ_ADDR srcAddr, byte[] groupMask, bool isSuppressPosRsp = false)
        {
            var (isPositive, data) = await _udsTpHandle.UdsRequestAsync(
                reqAddr: srcAddr,
                isSuppressPosRsp: isSuppressPosRsp,
                serviceId: 0x14,
                subFunction: groupMask,
                parameter: null);
            if (!isPositive)
            {
                byte? nrc = data?.Length > 0 ? data[0] : (byte?)null;
                throw new ProgrammingException("14清除DTC失败", nrc);
            }
        }

        // 封装27解锁方法
        private async Task UDS27_SecurityAsync(byte subFun, byte level)
        {
            var (isPositive, data) = await _udsTpHandle.UdsRequestAsync(
                reqAddr: UDS_TP.REQ_ADDR.PHY_ADDR,
                isSuppressPosRsp: false,
                serviceId: 0x27,
                subFunction: new byte[] { subFun },
                parameter: null);
            if (!isPositive)
            {
                byte? nrc = data?.Length > 0 ? data[0] : (byte?)null;
                throw new ProgrammingException("27请求种子失败", nrc);
            }
            byte[] Seed = data.Skip(2).ToArray();// 剔除67 XX回复信息
            byte[] Key = ZLG27Algorithm.Securityalgorithm(Seed, level);// 计算秘钥

            (isPositive, data) = await _udsTpHandle.UdsRequestAsync(
                reqAddr: UDS_TP.REQ_ADDR.PHY_ADDR,
                isSuppressPosRsp: false,
                serviceId: 0x27,
                subFunction: new byte[] { (byte)(subFun + 1U) },
                parameter: Key);
            if (!isPositive)
            {
                byte? nrc = data?.Length > 0 ? data[0] : (byte?)null;
                throw new ProgrammingException("27解锁失败", nrc);
            }
        }

        // 封装2E方法
        private async Task UDS2E_DataWriteAsync(byte[] subFun, byte[] parm, string warmInfo = null)
        {
            var (isPositive, data) = await _udsTpHandle.UdsRequestAsync(
                reqAddr: UDS_TP.REQ_ADDR.PHY_ADDR,
                isSuppressPosRsp: false,
                serviceId: 0x2E,
                subFunction: subFun,
                parameter: parm);
            if (!isPositive)
            {
                byte? nrc = data?.Length > 0 ? data[0] : (byte?)null;
                throw new ProgrammingException("2E" + warmInfo + "失败", nrc);
            }
        }

        // 封装31方法
        private async Task UDS31_RoutineCtrlAsync(byte[] subFun, string warmInfo = null)
        {
            var (isPositive, data) = await _udsTpHandle.UdsRequestAsync(
                reqAddr: UDS_TP.REQ_ADDR.PHY_ADDR,
                isSuppressPosRsp: false,
                serviceId: 0x31,
                subFunction: subFun,
                parameter: null);
            if (!isPositive)
            {
                byte? nrc = data?.Length > 0 ? data[0] : (byte?)null;
                throw new ProgrammingException("31" + warmInfo + "失败", nrc);
            }
        }
        private async Task UDS31_RoutineCtrlAsync(byte[] subFun, byte[] parm, string warmInfo)
        {
            var (isPositive, data) = await _udsTpHandle.UdsRequestAsync(
                reqAddr: UDS_TP.REQ_ADDR.PHY_ADDR,
                isSuppressPosRsp: false,
                serviceId: 0x31,
                subFunction: subFun,
                parameter: parm);
            if (!isPositive)
            {
                byte? nrc = data?.Length > 0 ? data[0] : (byte?)null;
                throw new ProgrammingException("31" + warmInfo + "失败", nrc);
            }
        }

        // 封装34请求下载方法
        private async Task<uint> UDS34_RequestAsync(uint startAddr, uint dataLen)
        {
            // 请求数据下载
            byte[] parm34 = new byte[1 + 4 + 4];
            parm34[0] = 0x44;

            parm34[1] = (byte)((startAddr >> 24) & 0xFF);
            parm34[2] = (byte)((startAddr >> 16) & 0xFF);
            parm34[3] = (byte)((startAddr >> 8) & 0xFF);
            parm34[4] = (byte)((startAddr) & 0xFF);

            parm34[5] = (byte)((dataLen >> 24) & 0xFF);
            parm34[6] = (byte)((dataLen >> 16) & 0xFF);
            parm34[7] = (byte)((dataLen >> 8) & 0xFF);
            parm34[8] = (byte)((dataLen) & 0xFF);

            var (isPositive, data) = await _udsTpHandle.UdsRequestAsync(
                reqAddr: UDS_TP.REQ_ADDR.PHY_ADDR,
                isSuppressPosRsp: false,
                serviceId: 0x34,
                subFunction: new byte[] { 0x00 },
                parameter: parm34);
            if (!isPositive)
            {
                byte? nrc = data?.Length > 0 ? data[0] : (byte?)null;
                throw new ProgrammingException("34请求下载失败", nrc);
            }
            // 获取ECU最大块长度，定死成2字节
            //uint addrSize = (data[2] & 0xF0U) >> 8;
            uint blockSize = ((uint)data[3] << 8) | ((uint)data[4]);// 计算最大块长度
            return blockSize;
        }

        private async Task<uint> UDS34_RequestAsync(uint startAddr, uint dataLen, string warmInfo)
        {
            // 请求数据下载
            byte[] parm34 = new byte[1 + 4 + 4];
            parm34[0] = 0x44;

            parm34[1] = (byte)((startAddr >> 24) & 0xFF);
            parm34[2] = (byte)((startAddr >> 16) & 0xFF);
            parm34[3] = (byte)((startAddr >> 8) & 0xFF);
            parm34[4] = (byte)((startAddr) & 0xFF);

            parm34[5] = (byte)((dataLen >> 24) & 0xFF);
            parm34[6] = (byte)((dataLen >> 16) & 0xFF);
            parm34[7] = (byte)((dataLen >> 8) & 0xFF);
            parm34[8] = (byte)((dataLen) & 0xFF);

            var (isPositive, data) = await _udsTpHandle.UdsRequestAsync(
                reqAddr: UDS_TP.REQ_ADDR.PHY_ADDR,
                isSuppressPosRsp: false,
                serviceId: 0x34,
                subFunction: new byte[] { 0x00 },
                parameter: parm34);
            if (!isPositive)
            {
                byte? nrc = data?.Length > 0 ? data[0] : (byte?)null;
                throw new ProgrammingException("34" + warmInfo + "请求下载失败", nrc);
            }
            // 获取ECU最大块长度，定死成2字节
            //uint addrSize = (data[1] & 0xF0U) >> 8;
            uint blockSize = ((uint)data[2] << 8) | ((uint)data[3]);// 计算最大块长度
            return blockSize;
        }

        // 封装36刷写方法
        private async Task UDS36_TransferAsync(FlashFile flashFile, uint blockSize)
        {
            uint offset = 0;
            byte seq = 0x01;
            while (offset < flashFile.Data.Length)
            {
                uint remaining = (uint)(flashFile.Data.Length - offset);
                uint size = Math.Min(remaining, blockSize - 2);

                byte[] frame = new byte[size];

                Buffer.BlockCopy(flashFile.Data, (int)offset, frame, 0, (int)size);

                var (isPositive, data) = await _udsTpHandle.UdsRequestAsync(
                    reqAddr: UDS_TP.REQ_ADDR.PHY_ADDR,
                    isSuppressPosRsp: false,
                    serviceId: 0x36,
                    subFunction: new byte[] { seq },
                    parameter: frame);
                if (!isPositive)
                {
                    byte? nrc = data?.Length > 0 ? data[0] : (byte?)null;
                    throw new ProgrammingException("36写入失败", nrc);
                }
                offset += size;
                seq = (byte)((seq + 1) & 0xFF);
            }
        }

        private async Task UDS36_TransferAsync(FlashFile flashFile, uint blockSize, string warmInfo)
        {
            uint offset = 0;
            byte seq = 0x01;
            while (offset < flashFile.Data.Length)
            {
                uint remaining = (uint)(flashFile.Data.Length - offset);
                uint size = Math.Min(remaining, blockSize - 2);

                byte[] frame = new byte[size];

                Buffer.BlockCopy(flashFile.Data, (int)offset, frame, 0, (int)size);

                var (isPositive, data) = await _udsTpHandle.UdsRequestAsync(
                    reqAddr: UDS_TP.REQ_ADDR.PHY_ADDR,
                    isSuppressPosRsp: false,
                    serviceId: 0x36,
                    subFunction: new byte[] { seq },
                    parameter: frame);
                if (!isPositive)
                {
                    byte? nrc = data?.Length > 0 ? data[0] : (byte?)null;
                    throw new ProgrammingException("36" + warmInfo + "写入失败", nrc);
                }
                offset += size;
                seq = (byte)((seq + 1) & 0xFF);
            }
        }

        // 封装37结束下载方法
        private async Task UDS37_EndTransAsync()
        {
            var (isPositive, data) = await _udsTpHandle.UdsRequestAsync(
                reqAddr: UDS_TP.REQ_ADDR.PHY_ADDR,
                isSuppressPosRsp: false,
                serviceId: 0x37,
                subFunction: null,
                parameter: null);
            if (!isPositive)
            {
                byte? nrc = data?.Length > 0 ? data[0] : (byte?)null;
                throw new ProgrammingException("37退出下载失败", nrc);
            }
        }
        private async Task UDS37_EndTransAsync(string warmInfo = null)
        {
            var (isPositive, data) = await _udsTpHandle.UdsRequestAsync(
                reqAddr: UDS_TP.REQ_ADDR.PHY_ADDR,
                isSuppressPosRsp: false,
                serviceId: 0x37,
                subFunction: null,
                parameter: null);
            if (!isPositive)
            {
                byte? nrc = data?.Length > 0 ? data[0] : (byte?)null;
                throw new ProgrammingException("37" + warmInfo + "退出下载失败", nrc);
            }
        }

        // 封装85 DTC记录控制方法
        private async Task UDS85_DtcControlAsync(UDS_TP.REQ_ADDR srcAddr, byte subFun, string warmInfo = null)
        {
            var (isPositive, data) = await _udsTpHandle.UdsRequestAsync(
                reqAddr: srcAddr,
                isSuppressPosRsp: false,
                serviceId: 0x85,
                subFunction: new byte[] { subFun },
                parameter: null);
            if (!isPositive)
            {
                byte? nrc = data?.Length > 0 ? data[0] : (byte?)null;
                throw new ProgrammingException("85" + warmInfo + "失败", nrc);
            }
        }
        private async Task UDS85_DtcControlAsync(UDS_TP.REQ_ADDR srcAddr, byte subFun, bool isSuppressPosRsp, string warmInfo = null)
        {
            var (isPositive, data) = await _udsTpHandle.UdsRequestAsync(
                reqAddr: srcAddr,
                isSuppressPosRsp: isSuppressPosRsp,
                serviceId: 0x85,
                subFunction: new byte[] { subFun },
                parameter: null);
            if (!isPositive)
            {
                byte? nrc = data?.Length > 0 ? data[0] : (byte?)null;
                throw new ProgrammingException("85" + warmInfo + "失败", nrc);
            }
        }

        // 封装28 DTC记录控制方法
        private async Task UDS28_MsgControlAsync(UDS_TP.REQ_ADDR srcAddr, byte subFun, byte parm, string warmInfo = null)
        {
            var (isPositive, data) = await _udsTpHandle.UdsRequestAsync(
                reqAddr: srcAddr,
                isSuppressPosRsp: false,
                serviceId: 0x28,
                subFunction: new byte[] { subFun },
                parameter: new byte[] { parm });
            if (!isPositive)
            {
                byte? nrc = data?.Length > 0 ? data[0] : (byte?)null;
                throw new ProgrammingException("28" + warmInfo + "失败", nrc);
            }
        }
        private async Task UDS28_MsgControlAsync(UDS_TP.REQ_ADDR srcAddr, byte subFun, byte parm, bool isSuppressPosRsp, string warmInfo = null)
        {
            var (isPositive, data) = await _udsTpHandle.UdsRequestAsync(
                reqAddr: srcAddr,
                isSuppressPosRsp: isSuppressPosRsp,
                serviceId: 0x28,
                subFunction: new byte[] { subFun },
                parameter: new byte[] { parm });
            if (!isPositive)
            {
                byte? nrc = data?.Length > 0 ? data[0] : (byte?)null;
                throw new ProgrammingException("28" + warmInfo + "失败", nrc);
            }
        }
    }

    public class CheckSum
    {
        // 计算SHA256
        public static byte[] Sha256(byte[] input)
        {
            var sha256 = SHA256.Create();
            return sha256.ComputeHash(input);
        }

        // 计算CRC32
        public static byte[] CRC32(byte[] input)
        {
            // 传入数据为空返回空
            if (input == null || input.Length == 0)
                return Array.Empty<byte>();

            uint crc32 = 0xFFFFFFFF; // 初始化为全1
            for (int i = 0; i < input.Length; i++)
            {
                byte tableIndex = (byte)((crc32 ^ input[i]) & 0xFF);
                crc32 = (crc32 >> 8) ^ crc32Table[tableIndex];
            }
            crc32 = ~crc32;

            // 直接返回大端字节序的 CRC
            return new byte[]
            {
                (byte)(crc32 >> 24),
                (byte)(crc32 >> 16),
                (byte)(crc32 >> 8),
                (byte)crc32
            };
        }

        // crc32查表
        private static readonly uint[] crc32Table = new uint[]
        {
            0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA,
            0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
            0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
            0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
            0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE,
            0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
            0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC,
            0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
            0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
            0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
            0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940,
            0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
            0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116,
            0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
            0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
            0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
            0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A,
            0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
            0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818,
            0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
            0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
            0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
            0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C,
            0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
            0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2,
            0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
            0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
            0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
            0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086,
            0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
            0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4,
            0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
            0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
            0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
            0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8,
            0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
            0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE,
            0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
            0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
            0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
            0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252,
            0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
            0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60,
            0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
            0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
            0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
            0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04,
            0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
            0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A,
            0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
            0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
            0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
            0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E,
            0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
            0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C,
            0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
            0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
            0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
            0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0,
            0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
            0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6,
            0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
            0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
            0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D,
            };
    }
}
